package com.dj.mingkong.portal.biz.core.base.context;

import com.dj.mingkong.common.constant.RedisConstants;
import com.dj.mingkong.common.infrastructure.base.dto.context.UserInfoContext;
import com.dj.mingkong.portal.biz.constant.Constants;
import com.dj.mingkong.portal.biz.util.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 用户核心
 *
 * @author zenglonghui
 * @date: 2022/8/22 18:34
 */
@Slf4j
@Component
public class UserContextHolder {
    @Resource
    JwtUtil jwtUtil;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 未拦截时获取当前登录用户（未登录返回null）
     *
     * @return UserInfoContext
     */
    public UserInfoContext getCurrentUser() {
        //获取当前线程绑定的request对象
        final ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.nonNull(requestAttributes)) {
            final HttpServletRequest request = requestAttributes.getRequest();
            final String token = getToken(request);
            log.info("Authorization:{}", token);
            if (StringUtils.isBlank(token) || Constants.UNDEFINED.equals(token)) {
                return null;
            }
            //解析token
            final UserInfoContext userInfoContext = jwtUtil.getUserInfoFromToken(token, UserInfoContext.class);
            log.info("解析token的信息userInfoContext:{}", Objects.isNull(userInfoContext) ? "null" : userInfoContext.toString());
            if (Objects.isNull(userInfoContext)) {
                return null;
            }
            //校验角色
            final List<String> roles = jwtUtil.getRolesFromToken(token);
            log.info("解析token的信息roles:{}", roles.toString());
            if (CollectionUtils.isEmpty(roles)) {
                return null;
            }

            final String redisToken = redisTemplate.boundValueOps(RedisConstants.TOKEN + userInfoContext.getUsername()).get();
            if (StringUtils.isBlank(redisToken)) {
                return null;
            }

            if (!redisToken.equalsIgnoreCase(token)) {
                return null;
            }
            return userInfoContext;
        }
        return null;
    }

    public Optional<UserInfoContext> getCurrentUserOpt() {
        //获取当前线程绑定的request对象
        final ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.nonNull(requestAttributes)) {
            final HttpServletRequest request = requestAttributes.getRequest();
            final String token = getToken(request);
            log.info("Authorization:{}", token);
            if (StringUtils.isBlank(token) || Constants.UNDEFINED.equals(token)) {
                return Optional.empty();
            }
            //解析token
            final UserInfoContext userInfoContext = jwtUtil.getUserInfoFromToken(token, UserInfoContext.class);
            log.info("解析token的信息userInfoContext:{}", Objects.isNull(userInfoContext) ? "null" : userInfoContext.toString());
            if (Objects.isNull(userInfoContext)) {
                return Optional.empty();
            }
            //校验角色
            final List<String> roles = jwtUtil.getRolesFromToken(token);
            log.info("解析token的信息roles:{}", roles.toString());
            if (CollectionUtils.isEmpty(roles)) {
                return Optional.empty();
            }

            final String redisToken = redisTemplate.boundValueOps(RedisConstants.TOKEN + userInfoContext.getUsername()).get();
            if (StringUtils.isBlank(redisToken)) {
                return Optional.empty();
            }

            if (!redisToken.equalsIgnoreCase(token)) {
                return Optional.empty();
            }
            return Optional.of(userInfoContext);
        }
        return Optional.empty();
    }

    public String getToken(HttpServletRequest request) {
        final String headerToken = request.getHeader(Constants.AUTHORIZATION);
        if (StringUtils.isNotBlank(headerToken)) {
            return headerToken;
        } else if (StringUtils.isNotBlank(request.getQueryString())) {
            final String queryString = request.getQueryString();
            final String[] params = queryString.split("&");
            for (String param : params) {
                final String[] arr = param.split("=");
                if ("token".equalsIgnoreCase(arr[0])) {
                    return arr[1];
                }
            }
        }

        final Cookie[] cookies = request.getCookies();
        if (Objects.isNull(cookies)) {
            return null;
        }
        for (Cookie cookie : cookies) {
            if (Constants.AUTHORIZATION.equals(cookie.getName()) && StringUtils.isNotEmpty(cookie.getValue()) && cookie.getValue().length() > 2) {
                return cookie.getValue();
            }
        }
        return null;
    }
}
